package com.lihepeng.leecode.linkedList;

import org.junit.Test;

import java.util.ArrayList;
import java.util.List;

/**
 * 给定一个单链表 L：L0→L1→…→Ln-1→Ln ，
 * 将其重新排列后变为： L0→Ln→L1→Ln-1→L2→Ln-2→…
 * <p>
 * 你不能只是单纯的改变节点内部的值，而是需要实际的进行节点交换。
 * <p>
 * 示例 1:
 * <p>
 * 给定链表 1->2->3->4, 重新排列为 1->4->2->3.
 * <p>
 * 来源：力扣（LeetCode）
 * 链接：https://leetcode-cn.com/problems/reorder-list
 * 著作权归领扣网络所有。商业转载请联系官方授权，非商业转载请注明出处。
 */
public class Solution143 {
    // 使用线性表进行存储，然后通过下标访问重新构建
    public void reorderList(ListNode head) {
        if (head == null) {
            return;
        }
        List<ListNode> list = new ArrayList();
        ListNode currentNode = head;
        while (currentNode != null) {
            list.add(currentNode);
            currentNode = currentNode.next;
        }
        int size = list.size();
        int i = 0;
        int j = size - 1;
        while (i < j) {
            list.get(i).next = list.get(j);
            i++;
            if (i == j) {
                break;
            }
            list.get(j).next = list.get(i);
            j--;
        }
        list.get(i).next = null;

    }

    // 寻找链表中点
    // 反转链表
    // 合并链表
    // 寻找中间节点
    public void reorderList01(ListNode head) {
        ListNode middleNode = middleNode(head);
        ListNode nextNode = middleNode.next;
        middleNode.next = null;
        ListNode listNode1 = revertseList(nextNode);
        mergeList(head, listNode1);
    }

    public ListNode middleNode(ListNode head) {
        ListNode fast = head;
        ListNode slow = head;
        while (fast != null && fast.next != null) {
            slow = slow.next;
            fast = fast.next.next;
        }
        return slow;
    }

    public ListNode revertseList(ListNode node) {
        ListNode prev = null;
        ListNode current = node;
        while (current != null) {
            ListNode nextTemp = current.next;
            current.next = prev;
            prev = current;
            current = nextTemp;
        }

        return prev;
    }

    public void mergeList(ListNode l1, ListNode l2) {
        ListNode l1Temp = null;
        ListNode l2Temp = null;
        while (l1 != null && l2 != null) {
            l1Temp = l1.next;
            l2Temp = l2.next;
            l1.next = l2;
            l1 = l1Temp;
            l2.next = l1;
            l2 = l2Temp;
        }

    }

    @Test
    public void runTest() {
        ListNode head = new ListNode(0);
        ListNode n1 = new ListNode(1);
        ListNode n2 = new ListNode(2);
        ListNode n3 = new ListNode(3);
        ListNode n4 = new ListNode(4);
        head.next = n1;
        n1.next = n2;
        n2.next = n3;
        n3.next = n4;
        reorderList01(head);
        System.out.println(head);
    }
}
